#! /usr/bin/python
ident = '$Id: binders.py 109 2006-06-05 18:46:37Z trevor $'
'''Defines the base rex objects class. All rex objects are derived from this class to
standerdize the xml serialization process.
Child classes define their own data dictionary with the properties they are interested in.
'''
import accounts, base, common, re
from   xml.sax 	import saxutils
from   xml.dom	import minidom

# This mirror pattern will be used to find mirror binders
mirror_pattern = re.compile( "^[ \t]*\<\#[ \t]*\((.*)\)[ \t]*=[ \t]*\((.*)\)[ \t]*\.[ \t]*\#\>[ \t]*$" )

################################
class binder( base.object ):
	'''Represents the rex binder objects'''
	def __init__( self, account, xmlstring = None ):
		assert account, 'No account passed'
		self.module = 'base'
		self.data = []
		self.data.append( {'name':'id',			'value':'', 'label':'ID', 		'type':base.ROT_NUMBER,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'name',		'value':'', 'label':'Name', 	'type':base.ROT_TEXT,	'rw':True,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'description','value':'', 'label':'Description','type':base.ROT_TEXT,	'rw':True,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'mirror_id',	'value':'', 'label':'Mirror',	'type':base.ROT_TEXT,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'kind',		'value':'', 'label':'Kind',		'type':base.ROT_TEXT,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'created_on',	'value':'', 'label':'Created On','type':base.ROT_DATE,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.object_name	= "binder"
		self.variables		= []
		self.instances 		= []
		self.optimizations	= []
		self.mirror			= False
		self.mirror_name	= ""
		self.original_name	= ""
		self.tree_item		= None
		self.otree_item		= None
		self.editor			= None
		base.object.__init__( self, account, 'base', xmlstring )

	def fromxml( self, xmlstring ):
		# Call the base method to handle the attributes, then we parse the instances
		base.object.fromxml( self, xmlstring )
		if self['mirror_id'].isdigit() and int( self['mirror_id'] ) > 0:
			self.mirror			= True
			obinder				= self.get_real_binder()
			self.original_name	= obinder['name']

		# Now parse all the variable/instances
		xmlstring = common.uni2str( xmlstring )
		sdom 	= minidom.parseString( xmlstring )
		snode	= sdom.firstChild
		# variables
		for inode in snode.getElementsByTagName("variable"):
			var = variable( self.account, self, inode.toxml() )
			var["binder_id"] = self["id"]
			self.variables.append( var )
			del inode
		# optimizations
		for inode in snode.getElementsByTagName("optimization"):
			opt = optimization( self.account, self, inode.toxml() )
			opt["binder_id"] = self["id"]
			self.optimizations.append( opt )
			del inode
		del snode
		del sdom

	def get_real_binder( self ):
		if not self.mirror: return self
		for b in self.account.window.binder_control.binders:
			if b['id'] == self['mirror_id']:
				return b
		return None

	def create( self ):
		self['id'] = self.execute( "create", dom=self.toxml() )
		return True

class variable( base.object ):
	'''Represents the variable class'''
	def __init__( self, account, binder = None, xmlstring = None ):
		self.data = []
		self.data.append( {'name':'binder_id',	'value':'', 'label':'binder_id',	'type':base.ROT_NUMBER,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'name',		'value':'', 'label':'Name',			'type':base.ROT_TEXT,	'rw':True,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'new_name',	'value':'', 'label':'Name',			'type':base.ROT_TEXT,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.object_name = "variable"
		self.binder      = binder
		if binder is not None:
			self.module		 = binder.module
			if ( binder["kind"] == "SYSTEM" ) and ( binder["name"] == "CONTACT" ):
				self["binder_id"] = "contact"
			else:
				self["binder_id"] = binder["id"]
		base.object.__init__( self, account, 'base', xmlstring )

	def create( self, new_name ):
		#common.dprint( "Creating variable binder_id %s" % self["binder_id"] )
		self['name'] = new_name
		return self.execute( "create", dom=self.toxml() )

	def delete( self ):
		if ( self.binder["kind"] == "SYSTEM" ) and ( self.binder["name"] == "CONTACT" ):
			self["binder_id"] = "contact"
		else:
			self["binder_id"] = self.binder["id"]
		dom = "<variable name=%s binder_id=%s />" %( saxutils.quoteattr( self['name'] ), saxutils.quoteattr( self['binder_id'] ) )
		return self.execute( "delete", DOM=dom  )

	def	save( self ):
		'''Saves the object on the server, then save all it's variable values'''
		if self.binder is not None:
			if ( self.binder["kind"] == "SYSTEM" ) and ( self.binder["name"] == "CONTACT" ):
				self["binder_id"] = "contact"
			else:
				self["binder_id"] = self.binder["id"]
		return base.object.save( self )

# at the moment the variable class only exists to parse the variable data for the binder
class optimization( base.object ):
	def __init__( self, account, binder = None, xmlstring = None ):
		self.data = []
		self.data.append( {'name':'binder_id',	'value':'', 'label':'binder_id',	'type':base.ROT_NUMBER,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'name',		'value':'', 'label':'Name',			'type':base.ROT_TEXT,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'unique',		'value':'', 'label':'Unique',		'type':base.ROT_NUMBER,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'variables',	'value':'', 'label':'Variables',	'type':base.ROT_TEXT,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		# directions: 'False' = ASCENDING (default), 'True' = DESCENDING
		self.data.append( {'name':'directions',	'value':'', 'label':'Directions',	'type':base.ROT_TEXT,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.object_name = "optimization"
		self.binder      = binder
		if binder is not None:
			self.module		 = binder.module
			if ( binder["kind"] == "SYSTEM" ) and ( binder["name"] == "CONTACT" ):
				self["binder_id"] = "contact"
			else:
				self["binder_id"] = binder["id"]
		base.object.__init__( self, account, 'base', xmlstring )

	def create( self ):
		#common.dprint( "Creating optimization for binder_id %s" % self["binder_id"] )
		ret = ''
		ret = self.execute( "create", dom=self.toxml() )
		if ret != '':
			self['name'] = ret
		return ret

	def delete( self ):
		return self.execute( "delete", NAME=self['name']  )

	def	save( self ):
		return False

class instance( base.object ):
	def __init__( self, account, binder, xmlstring = None ):
		assert account, 'No account passed'
		self.data = []
		self.data.append( {'name':'instance_id',	'value':'', 'label':'instance_id', 	'type':base.ROT_NUMBER,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'instance_name',	'value':'', 'label':'instance_name','type':base.ROT_TEXT,	'rw':True,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'binder_id',		'value':'', 'label':'binder_id',	'type':base.ROT_TEXT,	'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.data.append( {'name':'created_on',		'value':'', 'label':'created_on',	'type':base.ROT_TEXT,'rw':False,	'file_upload':False,	'options':None,	'custom':False, 'dirty':False } )
		self.object_name = "instance"
		self.binder      = binder
		self.module		 = binder.module
		if binder is not None:
			self["binder_id"] = binder["id"]
		self.values		 = []
		base.object.__init__( self, account, 'base', xmlstring )

	def fromxml( self, xmlstring ):
		# Call the base method to handle the attributes, then we parse the values
		base.object.fromxml( self, xmlstring )

	def	save( self ):
		newid = base.object.save2( self )
		self["instance_id"] = newid
		return newid

	def create( self ):
		self['instance_id'] = self.execute( "create", dom=self.toxml() )
		return True

	def delete( self ):
		dom = "<instance id=\"%s\" binder_id=\"%s\" />" % ( self['instance_id'], self.binder['id'] )
		return self.execute( "delete", dom=dom )

	def clone( self ):
		dom = "<instance id=\"%s\" binder_id=\"%s\" />" % ( self['instance_id'], self.binder['id'] )
		return self.execute( "clone", dom=dom )
